package com.zhny.iot.yy.collect.gateway.plugin;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.mqtt.MqttDevice;
import com.zhny.iot.yy.collect.gateway.plugin.model.YYCollectGatewayStoreEntry;
import io.netty.util.internal.StringUtil;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.pf4j.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.function.BiConsumer;

public class YYCollectGatewayDevice extends MqttDevice<YYCollectGatewayConfig> {
    public YYCollectGatewayDevice(IDeviceFactory<YYCollectGatewayConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super (factory, centerFacilities, entity);
    }

    @Override
    protected String[] getSubscribeTopics() {
        check();
        return new String[]{
                this.getConfig ().getTopic ()
        };
    }

    @Override
    protected BiConsumer<String, MqttMessage> getMessageCallback() {
        return (topic,msg)->{
            byte[] buf = msg.getPayload ();
            try {
                String payload = new String(buf,"utf-8");
                logger.info ("主题：{},内容:{}",topic,payload);
                Map<String,Integer> bodyMap = mapTo (payload, new TypeReference<Map<String, Integer>> () {
                });
                if(bodyMap != null){
                    YYCollectGatewayStoreEntry entry = new YYCollectGatewayStoreEntry ();
                    entry.setDissolvedOxygen1 (String.valueOf (bodyMap.get ("dissolvedOxygen1")/100.00));
                    entry.setTemperature1 (String.valueOf (bodyMap.get ("temperature1")/10.00));
                    entry.setDissolvedOxygen2 (String.valueOf (bodyMap.get ("dissolvedOxygen2")/100.00));
                    entry.setTemperature2 (String.valueOf (bodyMap.get ("temperature2")/10.00));
                    entry.setDissolvedOxygen3 (String.valueOf (bodyMap.get ("dissolvedOxygen3")/100.00));
                    entry.setPh3 (String.valueOf (bodyMap.get ("ph3")/100.00));
                    entry.setTemperature3 (String.valueOf (bodyMap.get ("temperature3")/10.00));
                    saveReal (entry);
                    save (entry);
                    logger.info (entry.toString ());
                    MessageEntry msgEntry =MessageUtils.createMessageEntry (this.getId ());
                    msgEntry.setType (MessageType.RESULT);
                    msgEntry.setData (entry);
                    nofity (msgEntry);
                }

            } catch (UnsupportedEncodingException e) {
                logger.error ("消息解码失败！",e);
            }
        };
    }

    private void check(){
        YYCollectGatewayConfig config = this.getConfig ();
        if(config == null)
            throw new NullPointerException ("渔业数据采集网关配置必填！");
        String topic = config.getTopic ();
        String host = config.getHost ();
        String userName = config.getUserName ();
        String passWord = config.getPassWord ();
        String clientId = config.getClientId ();
        if(StringUtils.isNullOrEmpty (topic))
            throw new NullPointerException ("渔业数据采集网关数据订阅主题必填");
        if(StringUtils.isNullOrEmpty (host))
            throw new NullPointerException ("渔业数据采集网关mqtt地址必填");
        if(StringUtils.isNullOrEmpty (userName))
            throw new NullPointerException ("渔业数据采集网关mqtt账号必填");
        if(StringUtils.isNullOrEmpty (passWord))
            throw new NullPointerException ("渔业数据采集网关mqtt密码必填");
        if(StringUtils.isNullOrEmpty (clientId))
            throw new NullPointerException ("渔业数据采集网关mqtt客户端连接号必填");
    }

    private   <T> T mapTo(String body, TypeReference<T> valueTypeRef){
        if(StringUtil.isNullOrEmpty (body))
            return null;
        ObjectMapper mapper=new ObjectMapper ();
        try {
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            T obj=mapper.readValue (body,valueTypeRef);
            return obj;
        } catch (IOException e) {
            logger.info ("数据反序列化失败！",e);
            return null;
        }
    }
}
